package com.mh.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mh.dao.AccountBookDao;
import com.mh.dao.BillDao;
import com.mh.dto.vo.BillStatisticsOfBookVo;
import com.mh.dto.vo.R;
import com.mh.pojo.AccountBook;
import com.mh.pojo.Bill;
import com.mh.service.AccountBookService;
import com.mh.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 账本表(AccountBook)表服务实现类
 *
 * @author zmh
 * @since 2025-02-08 09:18:48
 */
@Service
@RequiredArgsConstructor
public class AccountBookServiceImpl extends ServiceImpl<AccountBookDao, AccountBook> implements AccountBookService {

    private final AccountBookDao accountBookDao;

    private final UserService  userService;

    private final BillDao billDao; // 账单操作


    /**
     * 分页查询
     *
     * @param page 查询页数
     * @param size 一页显示条数
     * @return ·
     */
    public R<Page<AccountBook>> getAllByPage(int page, int size) {
        Page<AccountBook> accountBookPage = new Page<>(page, size);
        LambdaQueryWrapper<AccountBook> queryWrapper = new LambdaQueryWrapper<>();
        //TODO 查询条件定制
        return R.success(accountBookDao.selectPage(accountBookPage, queryWrapper));
    }

    /**
     * 通过userId获取用户的所有账本
     * @param openId 用户id
     * @return ·
     */
    @Override
    public R<List<AccountBook>> getAll(String openId) {
        // 根据用户openId查询userId
        Integer userId = userService.getUserIdByOpenId(openId);
        // 构建查询条件
        LambdaQueryWrapper<AccountBook> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AccountBook::getUserId, userId);

        // 默排序：优先展示"默认账本"
        queryWrapper.orderByDesc(AccountBook::getIsDefault);
        List<AccountBook> accountBooks = accountBookDao.selectList(queryWrapper);

        if (accountBooks != null && accountBooks.size() > 0) {
            return R.success(accountBooks);
        }
        return R.error("查询失败或用户账本为空");
    }

    /**
     * 根据ID删除账本
     * @param userId 用户ID
     * @param bookId 账本ID
     * @return ·
     */
    @Override
    public R<Boolean> deleteById(Integer userId, Integer bookId) {
        // 检查当前删除的ID是否为默认账本的ID，如果是，需要筛选出其他非默认账本作为候选账本
        // 在候选账本中选出一本作为默认账本
        
        // 获取删除用户的所有账本
        LambdaQueryWrapper<AccountBook> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AccountBook::getUserId, userId);
        List<AccountBook> accountBooks = accountBookDao.selectList(queryWrapper);
        
        // 默认账本标识
        Integer isDefault = 0;
        // 候选账本
        List<AccountBook> candidateBooks = new ArrayList<>();

        for (AccountBook accountBook : accountBooks) {
            if (Objects.equals(accountBook.getId(), bookId)) {
                isDefault = accountBook.getIsDefault();
            }else{
                candidateBooks.add(accountBook);
            }
        }

        // 新的默认账本
        AccountBook newDefaultBook = null;

        // 判断是否为默认账本
        if(isDefault == 0){
            accountBookDao.deleteById(bookId);
            return R.success(true);
        }

        // 是默认，先删除，再在候选账本中选择一本作为默认账本。
        accountBookDao.deleteById(bookId);
        newDefaultBook = candidateBooks.get(0); // 选择候选中的第一个作为默认账本


        // 执行修改默认账本
        LambdaUpdateWrapper<AccountBook> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(AccountBook::getId, newDefaultBook.getId())
                .set(AccountBook::getIsDefault, 1);
        int update = accountBookDao.update(null, updateWrapper);

        return update > 0 ? R.success(true) : R.error("删除失败");

    }

    /**
     * 将账本设置默认
     * @param bookId 账本ID
     * @return ·
     */
    @Override
    public R<Boolean> setDefault(Integer bookId) {
        // 将原先的默认账本 默认状态取消
        LambdaUpdateWrapper<AccountBook> updateWrapper1 = new LambdaUpdateWrapper<>();
        updateWrapper1.eq(AccountBook::getIsDefault, 1)
                .set(AccountBook::getIsDefault, 0);

        if(accountBookDao.update(null, updateWrapper1) < 0){
            return R.error("设置失败");
        }

        // 执行修改默认账本
        LambdaUpdateWrapper<AccountBook> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(AccountBook::getId, bookId)
                .set(AccountBook::getIsDefault, 1);

        return accountBookDao.update(null, updateWrapper)>0? R.success(true) : R.error("设置失败");
    }

    /**
     * 改账本名称
     * @param bookId 账本ID
     * @param bookName 账本名称
     * @return ·
     * */
    @Override
    public R<Boolean> updateBookName(Integer bookId, String bookName) {
        LambdaUpdateWrapper<AccountBook> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(AccountBook::getId, bookId)
                .set(AccountBook::getName, bookName);

        if(accountBookDao.update(null, updateWrapper)>0){
            return R.success(true);
        }
        return R.error("修改名称失败");
    }

    /**
     * 新增账本
     * @param userId 用户ID
     * @param bookName 账本名称
     * @return ·
     */
    @Override
    public R<Boolean> addBook(Integer userId, String bookName) {
        AccountBook accountBook = new AccountBook();
        accountBook.setUserId(userId);
        accountBook.setName(bookName);
        if(accountBookDao.insert(accountBook)>0){
            return R.success(true);
        }
        return R.error("新增账本失败");
    }

    /**
     * 获取账本统计信息
     * @param bookIds 账本ID
     * @return ·
     */
    @Override
    public R<Map<Integer, BillStatisticsOfBookVo>> getBillStatisticsOfBook(List<Integer> bookIds) {
        // 构造返回的Map并初始化
        HashMap<Integer, BillStatisticsOfBookVo> returnMap = new HashMap<>();
        for (Integer bookId : bookIds) {
            returnMap.put(bookId, new BillStatisticsOfBookVo(bookId, 0, 0D, 0D, 0D));
        }


        // 获取账单数据
        LambdaQueryWrapper<Bill> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(Bill::getBookId, bookIds);
        List<Bill> bills = billDao.selectList(queryWrapper);

        // 遍历账单并更新每个账本的统计信息
        for (Bill bill : bills) {
            Integer bookId = bill.getBookId();
            BillStatisticsOfBookVo statistics = returnMap.get(bookId);

            if (bill.getType() == 2) { // 支出
                statistics.setExpenditure(statistics.getExpenditure() + bill.getAmount());
            } else { // 收入
                statistics.setIncome(statistics.getIncome() + bill.getAmount());
            }


            // 更新总账单数和余额
            statistics.setTotalBillNum(statistics.getTotalBillNum() + 1);
            statistics.setBalance(statistics.getIncome() - statistics.getExpenditure());

        }

        return R.success(returnMap);
    }

    /**
     * 获取首页账本统计数据（根据月份和账本ID获取指定月份的收入，支出和结余）
     * @param month 年月 2025
     * @param bookId 账本ID
     * @return `
     */
    @Override
    public R<BillStatisticsOfBookVo> getMonthDataOfAccountBook(String month, Integer bookId) {
        // 构造月份起始时间
        YearMonth yearMonth = YearMonth.parse(month, DateTimeFormatter.ofPattern("yyyy-MM"));
        LocalDateTime startOfMonth = yearMonth.atDay(1).atStartOfDay();
        LocalDateTime endOfMonth = yearMonth.atEndOfMonth().atTime(23, 59, 59);

        // 查询账单数据
        LambdaQueryWrapper<Bill> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Bill::getBookId, bookId)
                .between(Bill::getTransactionTime, startOfMonth, endOfMonth);
        List<Bill> bills = billDao.selectList(queryWrapper);

        BillStatisticsOfBookVo billStatisticsOfBookVo = new BillStatisticsOfBookVo(bookId, 0, 0D, 0D, 0D);

        // 遍历所有账单统计数据
        for (Bill bill : bills) {
            if (bill.getType() == 2) { // 支出
                billStatisticsOfBookVo.setExpenditure(billStatisticsOfBookVo.getExpenditure() + bill.getAmount());
            }else{
                billStatisticsOfBookVo.setIncome(billStatisticsOfBookVo.getIncome() + bill.getAmount());
            }
        }

        // 计算结余
        billStatisticsOfBookVo.setBalance(billStatisticsOfBookVo.getIncome() - billStatisticsOfBookVo.getExpenditure());
        return R.success(billStatisticsOfBookVo);
    }

}

